﻿#if (!UNITY_WEBGL || UNITY_EDITOR) && !BESTHTTP_DISABLE_ALTERNATE_SSL && !BESTHTTP_DISABLE_HTTP2

using System;
using System.Collections.Generic;

namespace BestHTTP.Connections.HTTP2
{
    static class HuffmanEncoder
    {
        public const UInt16 EOS = 256;

        public struct TableEntry
        {
            public UInt32 Code;
            public byte Bits;

            /// <summary>
            /// It must return 0 or 1 at bit index. Indexing will be relative to the Bits representing the current code. Idx grows from left to right. Idx must be between [1..Bits].
            /// </summary>
            public byte GetBitAtIdx(byte idx) 
            {
                return (byte)((this.Code >> (this.Bits - idx)) & 1);
            }

            public override string ToString()
            {
                return string.Format("[TableEntry Code: 0x{0:X}, Bits: {1}]", this.Code, this.Bits);
            }
        }

        public struct TreeNode
        {
            public UInt16 NextZeroIdx;
            public UInt16 NextOneIdx;

            public UInt16 Value;

            public override string ToString()
            {
                return string.Format("[TreeNode Value: {0}, NextZeroIdx: {1}, NextOneIdx: {2}]",
                    this.Value, this.NextZeroIdx, this.NextOneIdx);
            }
        }

        static TableEntry[] StaticTable = new TableEntry[257]
        {
            new TableEntry{ Code = 0x1ff8   , Bits = 13 },
            new TableEntry{ Code = 0x7fffd8 , Bits = 23 },
            new TableEntry{ Code = 0xfffffe2, Bits = 28 },
            new TableEntry{ Code = 0xfffffe3, Bits = 28 },
            new TableEntry{ Code = 0xfffffe4, Bits = 28 },
            new TableEntry{ Code = 0xfffffe5, Bits = 28 },
            new TableEntry{ Code = 0xfffffe6, Bits = 28 },
            new TableEntry{ Code = 0xfffffe7, Bits = 28 },
            new TableEntry{ Code = 0xfffffe8, Bits = 28 },
            new TableEntry{ Code = 0xffffea, Bits = 24 },
            new TableEntry{ Code = 0x3ffffffc , Bits = 30 },
            new TableEntry{ Code = 0xfffffe9 , Bits = 28 },
            new TableEntry{ Code = 0xfffffea , Bits = 28 },
            new TableEntry{ Code = 0x3ffffffd , Bits = 30 },
            new TableEntry{ Code = 0xfffffeb , Bits = 28 },
            new TableEntry{ Code = 0xfffffec , Bits = 28 },
            new TableEntry{ Code = 0xfffffed , Bits = 28 },
            new TableEntry{ Code = 0xfffffee , Bits = 28 },
            new TableEntry{ Code = 0xfffffef , Bits = 28 },
            new TableEntry{ Code = 0xffffff0 , Bits = 28 },
            new TableEntry{ Code = 0xffffff1 , Bits = 28 },
            new TableEntry{ Code = 0xffffff2 , Bits = 28 },
            new TableEntry{ Code = 0x3ffffffe, Bits = 30  },
            new TableEntry{ Code = 0xffffff3 , Bits = 28 },
            new TableEntry{ Code = 0xffffff4 , Bits = 28 },
            new TableEntry{ Code = 0xffffff5 , Bits = 28 },
            new TableEntry{ Code = 0xffffff6 , Bits = 28 },
            new TableEntry{ Code = 0xffffff7 , Bits = 28 },
            new TableEntry{ Code = 0xffffff8 , Bits = 28 },
            new TableEntry{ Code = 0xffffff9 , Bits = 28 },
            new TableEntry{ Code = 0xffffffa , Bits = 28 },
            new TableEntry{ Code = 0xffffffb , Bits = 28 },
            new TableEntry{ Code = 0x14 , Bits = 6 },
            new TableEntry{ Code = 0x3f8, Bits = 10  },
            new TableEntry{ Code = 0x3f9, Bits = 10  },
            new TableEntry{ Code = 0xffa, Bits = 12  },
            new TableEntry{ Code = 0x1ff9 , Bits = 13 },
            new TableEntry{ Code = 0x15 , Bits = 6 },
            new TableEntry{ Code = 0xf8 , Bits = 8 },
            new TableEntry{ Code = 0x7fa, Bits = 11  },
            new TableEntry{ Code = 0x3fa, Bits = 10  },
            new TableEntry{ Code = 0x3fb, Bits = 10  },
            new TableEntry{ Code = 0xf9 , Bits = 8 },
            new TableEntry{ Code = 0x7fb, Bits = 11  },
            new TableEntry{ Code = 0xfa , Bits = 8 },
            new TableEntry{ Code = 0x16 , Bits = 6 },
            new TableEntry{ Code = 0x17 , Bits = 6 },
            new TableEntry{ Code = 0x18 , Bits = 6 },
            new TableEntry{ Code = 0x0 , Bits = 5 },
            new TableEntry{ Code = 0x1 , Bits = 5 },
            new TableEntry{ Code = 0x2 , Bits = 5 },
            new TableEntry{ Code = 0x19 , Bits = 6 },
            new TableEntry{ Code = 0x1a , Bits = 6 },
            new TableEntry{ Code = 0x1b , Bits = 6 },
            new TableEntry{ Code = 0x1c , Bits = 6 },
            new TableEntry{ Code = 0x1d , Bits = 6 },
            new TableEntry{ Code = 0x1e , Bits = 6 },
            new TableEntry{ Code = 0x1f , Bits = 6 },
            new TableEntry{ Code = 0x5c , Bits = 7 },
            new TableEntry{ Code = 0xfb , Bits = 8 },
            new TableEntry{ Code = 0x7ffc , Bits = 15 },
            new TableEntry{ Code = 0x20 , Bits = 6 },
            new TableEntry{ Code = 0xffb, Bits = 12  },
            new TableEntry{ Code = 0x3fc, Bits = 10  },
            new TableEntry{ Code = 0x1ffa , Bits = 13 },
            new TableEntry{ Code = 0x21, Bits = 6  },
            new TableEntry{ Code = 0x5d, Bits = 7  },
            new TableEntry{ Code = 0x5e, Bits = 7  },
            new TableEntry{ Code = 0x5f, Bits = 7  },
            new TableEntry{ Code = 0x60, Bits = 7  },
            new TableEntry{ Code = 0x61, Bits = 7  },
            new TableEntry{ Code = 0x62, Bits = 7  },
            new TableEntry{ Code = 0x63, Bits = 7  },
            new TableEntry{ Code = 0x64, Bits = 7  },
            new TableEntry{ Code = 0x65, Bits = 7  },
            new TableEntry{ Code = 0x66, Bits = 7  },
            new TableEntry{ Code = 0x67, Bits = 7  },
            new TableEntry{ Code = 0x68, Bits = 7  },
            new TableEntry{ Code = 0x69, Bits = 7  },
            new TableEntry{ Code = 0x6a, Bits = 7  },
            new TableEntry{ Code = 0x6b, Bits = 7  },
            new TableEntry{ Code = 0x6c, Bits = 7  },
            new TableEntry{ Code = 0x6d, Bits = 7  },
            new TableEntry{ Code = 0x6e, Bits = 7  },
            new TableEntry{ Code = 0x6f, Bits = 7  },
            new TableEntry{ Code = 0x70, Bits = 7  },
            new TableEntry{ Code = 0x71, Bits = 7  },
            new TableEntry{ Code = 0x72, Bits = 7  },
            new TableEntry{ Code = 0xfc, Bits = 8  },
            new TableEntry{ Code = 0x73, Bits = 7  },
            new TableEntry{ Code = 0xfd, Bits = 8  },
            new TableEntry{ Code = 0x1ffb, Bits = 13  },
            new TableEntry{ Code = 0x7fff0, Bits = 19  },
            new TableEntry{ Code = 0x1ffc, Bits = 13  },
            new TableEntry{ Code = 0x3ffc, Bits = 14  },
            new TableEntry{ Code = 0x22, Bits = 6  },
            new TableEntry{ Code = 0x7ffd, Bits = 15  },
            new TableEntry{ Code = 0x3, Bits = 5  },
            new TableEntry{ Code = 0x23, Bits = 6  },
            new TableEntry{ Code = 0x4, Bits = 5  },
            new TableEntry{ Code = 0x24, Bits = 6  },
            new TableEntry{ Code = 0x5, Bits = 5  },
            new TableEntry{ Code = 0x25, Bits = 6  },
            new TableEntry{ Code = 0x26, Bits = 6  },
            new TableEntry{ Code = 0x27, Bits = 6  },
            new TableEntry{ Code = 0x6 , Bits = 5 },
            new TableEntry{ Code = 0x74, Bits = 7  },
            new TableEntry{ Code = 0x75, Bits = 7  },
            new TableEntry{ Code = 0x28, Bits = 6  },
            new TableEntry{ Code = 0x29, Bits = 6  },
            new TableEntry{ Code = 0x2a, Bits = 6  },
            new TableEntry{ Code = 0x7 , Bits = 5 },
            new TableEntry{ Code = 0x2b, Bits = 6  },
            new TableEntry{ Code = 0x76, Bits = 7  },
            new TableEntry{ Code = 0x2c, Bits = 6  },
            new TableEntry{ Code = 0x8 , Bits = 5 },
            new TableEntry{ Code = 0x9 , Bits = 5 },
            new TableEntry{ Code = 0x2d, Bits = 6  },
            new TableEntry{ Code = 0x77, Bits = 7  },
            new TableEntry{ Code = 0x78, Bits = 7  },
            new TableEntry{ Code = 0x79, Bits = 7  },
            new TableEntry{ Code = 0x7a, Bits = 7  },
            new TableEntry{ Code = 0x7b, Bits = 7  },
            new TableEntry{ Code = 0x7ffe, Bits = 15  },
            new TableEntry{ Code = 0x7fc, Bits = 11  },
            new TableEntry{ Code = 0x3ffd, Bits = 14  },
            new TableEntry{ Code = 0x1ffd, Bits = 13  },
            new TableEntry{ Code = 0xffffffc, Bits = 28  },
            new TableEntry{ Code = 0xfffe6 , Bits = 20 },
            new TableEntry{ Code = 0x3fffd2, Bits = 22  },
            new TableEntry{ Code = 0xfffe7 , Bits = 20 },
            new TableEntry{ Code = 0xfffe8 , Bits = 20 },
            new TableEntry{ Code = 0x3fffd3, Bits = 22  },
            new TableEntry{ Code = 0x3fffd4, Bits = 22  },
            new TableEntry{ Code = 0x3fffd5, Bits = 22  },
            new TableEntry{ Code = 0x7fffd9, Bits = 23  },
            new TableEntry{ Code = 0x3fffd6, Bits = 22  },
            new TableEntry{ Code = 0x7fffda, Bits = 23  },
            new TableEntry{ Code = 0x7fffdb, Bits = 23  },
            new TableEntry{ Code = 0x7fffdc, Bits = 23  },
            new TableEntry{ Code = 0x7fffdd, Bits = 23  },
            new TableEntry{ Code = 0x7fffde, Bits = 23  },
            new TableEntry{ Code = 0xffffeb, Bits = 24  },
            new TableEntry{ Code = 0x7fffdf, Bits = 23  },
            new TableEntry{ Code = 0xffffec, Bits = 24  },
            new TableEntry{ Code = 0xffffed, Bits = 24  },
            new TableEntry{ Code = 0x3fffd7, Bits = 22  },
            new TableEntry{ Code = 0x7fffe0, Bits = 23  },
            new TableEntry{ Code = 0xffffee, Bits = 24  },
            new TableEntry{ Code = 0x7fffe1, Bits = 23  },
            new TableEntry{ Code = 0x7fffe2, Bits = 23  },
            new TableEntry{ Code = 0x7fffe3, Bits = 23  },
            new TableEntry{ Code = 0x7fffe4, Bits = 23  },
            new TableEntry{ Code = 0x1fffdc, Bits = 21  },
            new TableEntry{ Code = 0x3fffd8, Bits = 22  },
            new TableEntry{ Code = 0x7fffe5, Bits = 23  },
            new TableEntry{ Code = 0x3fffd9, Bits = 22  },
            new TableEntry{ Code = 0x7fffe6, Bits = 23  },
            new TableEntry{ Code = 0x7fffe7, Bits = 23  },
            new TableEntry{ Code = 0xffffef, Bits = 24  },
            new TableEntry{ Code = 0x3fffda, Bits = 22  },
            new TableEntry{ Code = 0x1fffdd, Bits = 21  },
            new TableEntry{ Code = 0xfffe9 , Bits = 20 },
            new TableEntry{ Code = 0x3fffdb, Bits = 22  },
            new TableEntry{ Code = 0x3fffdc, Bits = 22  },
            new TableEntry{ Code = 0x7fffe8, Bits = 23  },
            new TableEntry{ Code = 0x7fffe9, Bits = 23  },
            new TableEntry{ Code = 0x1fffde, Bits = 21  },
            new TableEntry{ Code = 0x7fffea, Bits = 23  },
            new TableEntry{ Code = 0x3fffdd, Bits = 22  },
            new TableEntry{ Code = 0x3fffde, Bits = 22  },
            new TableEntry{ Code = 0xfffff0, Bits = 24  },
            new TableEntry{ Code = 0x1fffdf, Bits = 21  },
            new TableEntry{ Code = 0x3fffdf, Bits = 22  },
            new TableEntry{ Code = 0x7fffeb, Bits = 23  },
            new TableEntry{ Code = 0x7fffec, Bits = 23  },
            new TableEntry{ Code = 0x1fffe0, Bits = 21  },
            new TableEntry{ Code = 0x1fffe1, Bits = 21  },
            new TableEntry{ Code = 0x3fffe0, Bits = 22  },
            new TableEntry{ Code = 0x1fffe2, Bits = 21  },
            new TableEntry{ Code = 0x7fffed, Bits = 23  },
            new TableEntry{ Code = 0x3fffe1, Bits = 22  },
            new TableEntry{ Code = 0x7fffee, Bits = 23  },
            new TableEntry{ Code = 0x7fffef, Bits = 23  },
            new TableEntry{ Code = 0xfffea , Bits = 20 },
            new TableEntry{ Code = 0x3fffe2, Bits = 22  },
            new TableEntry{ Code = 0x3fffe3, Bits = 22  },
            new TableEntry{ Code = 0x3fffe4, Bits = 22  },
            new TableEntry{ Code = 0x7ffff0, Bits = 23  },
            new TableEntry{ Code = 0x3fffe5, Bits = 22  },
            new TableEntry{ Code = 0x3fffe6, Bits = 22  },
            new TableEntry{ Code = 0x7ffff1, Bits = 23  },
            new TableEntry{ Code = 0x3ffffe0, Bits = 26  },
            new TableEntry{ Code = 0x3ffffe1, Bits = 26  },
            new TableEntry{ Code = 0xfffeb , Bits = 20 },
            new TableEntry{ Code = 0x7fff1 , Bits = 19 },
            new TableEntry{ Code = 0x3fffe7, Bits = 22  },
            new TableEntry{ Code = 0x7ffff2, Bits = 23  },
            new TableEntry{ Code = 0x3fffe8, Bits = 22 },
            new TableEntry{ Code = 0x1ffffec, Bits = 25  },
            new TableEntry{ Code = 0x3ffffe2, Bits = 26  },
            new TableEntry{ Code = 0x3ffffe3, Bits = 26  },
            new TableEntry{ Code = 0x3ffffe4, Bits = 26  },
            new TableEntry{ Code = 0x7ffffde, Bits = 27  },
            new TableEntry{ Code = 0x7ffffdf, Bits = 27  },
            new TableEntry{ Code = 0x3ffffe5, Bits = 26  },
            new TableEntry{ Code = 0xfffff1 , Bits = 24 },
            new TableEntry{ Code = 0x1ffffed, Bits = 25  },
            new TableEntry{ Code = 0x7fff2 , Bits = 19 },
            new TableEntry{ Code = 0x1fffe3 , Bits = 21 },
            new TableEntry{ Code = 0x3ffffe6, Bits = 26  },
            new TableEntry{ Code = 0x7ffffe0, Bits = 27  },
            new TableEntry{ Code = 0x7ffffe1, Bits = 27  },
            new TableEntry{ Code = 0x3ffffe7, Bits = 26  },
            new TableEntry{ Code = 0x7ffffe2, Bits = 27  },
            new TableEntry{ Code = 0xfffff2 , Bits = 24 },
            new TableEntry{ Code = 0x1fffe4 , Bits = 21 },
            new TableEntry{ Code = 0x1fffe5 , Bits = 21 },
            new TableEntry{ Code = 0x3ffffe8, Bits = 26  },
            new TableEntry{ Code = 0x3ffffe9, Bits = 26  },
            new TableEntry{ Code = 0xffffffd, Bits = 28  },
            new TableEntry{ Code = 0x7ffffe3, Bits = 27  },
            new TableEntry{ Code = 0x7ffffe4, Bits = 27  },
            new TableEntry{ Code = 0x7ffffe5, Bits = 27  },
            new TableEntry{ Code = 0xfffec , Bits = 20 },
            new TableEntry{ Code = 0xfffff3, Bits = 24  },
            new TableEntry{ Code = 0xfffed , Bits = 20 },
            new TableEntry{ Code = 0x1fffe6, Bits = 21  },
            new TableEntry{ Code = 0x3fffe9, Bits = 22  },
            new TableEntry{ Code = 0x1fffe7, Bits = 21  },
            new TableEntry{ Code = 0x1fffe8, Bits = 21  },
            new TableEntry{ Code = 0x7ffff3, Bits = 23  },
            new TableEntry{ Code = 0x3fffea, Bits = 22  },
            new TableEntry{ Code = 0x3fffeb, Bits = 22  },
            new TableEntry{ Code = 0x1ffffee, Bits = 25  },
            new TableEntry{ Code = 0x1ffffef, Bits = 25  },
            new TableEntry{ Code = 0xfffff4 , Bits = 24 },
            new TableEntry{ Code = 0xfffff5 , Bits = 24 },
            new TableEntry{ Code = 0x3ffffea, Bits = 26  },
            new TableEntry{ Code = 0x7ffff4 , Bits = 23 },
            new TableEntry{ Code = 0x3ffffeb, Bits = 26  },
            new TableEntry{ Code = 0x7ffffe6, Bits = 27  },
            new TableEntry{ Code = 0x3ffffec, Bits = 26  },
            new TableEntry{ Code = 0x3ffffed, Bits = 26  },
            new TableEntry{ Code = 0x7ffffe7, Bits = 27  },
            new TableEntry{ Code = 0x7ffffe8, Bits = 27  },
            new TableEntry{ Code = 0x7ffffe9, Bits = 27  },
            new TableEntry{ Code = 0x7ffffea, Bits = 27  },
            new TableEntry{ Code = 0x7ffffeb, Bits = 27  },
            new TableEntry{ Code = 0xffffffe, Bits = 28  },
            new TableEntry{ Code = 0x7ffffec, Bits = 27  },
            new TableEntry{ Code = 0x7ffffed, Bits = 27  },
            new TableEntry{ Code = 0x7ffffee, Bits = 27  },
            new TableEntry{ Code = 0x7ffffef, Bits = 27  },
            new TableEntry{ Code = 0x7fffff0, Bits = 27  },
            new TableEntry{ Code = 0x3ffffee, Bits = 26  },
            new TableEntry{ Code = 0x3fffffff, Bits = 30  }
        };
        //static List<TreeNode> entries = new List<TreeNode>();

        static TreeNode[] HuffmanTree = new TreeNode[]
        {
            new TreeNode { Value = 0, NextZeroIdx = 98, NextOneIdx = 1 },
            new TreeNode { Value = 0, NextZeroIdx = 151, NextOneIdx = 2 },
            new TreeNode { Value = 0, NextZeroIdx = 173, NextOneIdx = 3 },
            new TreeNode { Value = 0, NextZeroIdx = 204, NextOneIdx = 4 },
            new TreeNode { Value = 0, NextZeroIdx = 263, NextOneIdx = 5 },
            new TreeNode { Value = 0, NextZeroIdx = 113, NextOneIdx = 6 },
            new TreeNode { Value = 0, NextZeroIdx = 211, NextOneIdx = 7 },
            new TreeNode { Value = 0, NextZeroIdx = 104, NextOneIdx = 8 },
            new TreeNode { Value = 0, NextZeroIdx = 116, NextOneIdx = 9 },
            new TreeNode { Value = 0, NextZeroIdx = 108, NextOneIdx = 10 },
            new TreeNode { Value = 0, NextZeroIdx = 11, NextOneIdx = 14 },
            new TreeNode { Value = 0, NextZeroIdx = 12, NextOneIdx = 166 },
            new TreeNode { Value = 0, NextZeroIdx = 13, NextOneIdx = 111 },
            new TreeNode { Value = 0, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 220, NextOneIdx = 15 },
            new TreeNode { Value = 0, NextZeroIdx = 222, NextOneIdx = 16 },
            new TreeNode { Value = 0, NextZeroIdx = 158, NextOneIdx = 17 },
            new TreeNode { Value = 0, NextZeroIdx = 270, NextOneIdx = 18 },
            new TreeNode { Value = 0, NextZeroIdx = 216, NextOneIdx = 19 },
            new TreeNode { Value = 0, NextZeroIdx = 279, NextOneIdx = 20 },
            new TreeNode { Value = 0, NextZeroIdx = 21, NextOneIdx = 27 },
            new TreeNode { Value = 0, NextZeroIdx = 377, NextOneIdx = 22 },
            new TreeNode { Value = 0, NextZeroIdx = 414, NextOneIdx = 23 },
            new TreeNode { Value = 0, NextZeroIdx = 24, NextOneIdx = 301 },
            new TreeNode { Value = 0, NextZeroIdx = 25, NextOneIdx = 298 },
            new TreeNode { Value = 0, NextZeroIdx = 26, NextOneIdx = 295 },
            new TreeNode { Value = 1, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 314, NextOneIdx = 28 },
            new TreeNode { Value = 0, NextZeroIdx = 50, NextOneIdx = 29 },
            new TreeNode { Value = 0, NextZeroIdx = 362, NextOneIdx = 30 },
            new TreeNode { Value = 0, NextZeroIdx = 403, NextOneIdx = 31 },
            new TreeNode { Value = 0, NextZeroIdx = 440, NextOneIdx = 32 },
            new TreeNode { Value = 0, NextZeroIdx = 33, NextOneIdx = 55 },
            new TreeNode { Value = 0, NextZeroIdx = 34, NextOneIdx = 46 },
            new TreeNode { Value = 0, NextZeroIdx = 35, NextOneIdx = 39 },
            new TreeNode { Value = 0, NextZeroIdx = 510, NextOneIdx = 36 },
            new TreeNode { Value = 0, NextZeroIdx = 37, NextOneIdx = 38 },
            new TreeNode { Value = 2, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 3, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 40, NextOneIdx = 43 },
            new TreeNode { Value = 0, NextZeroIdx = 41, NextOneIdx = 42 },
            new TreeNode { Value = 4, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 5, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 44, NextOneIdx = 45 },
            new TreeNode { Value = 6, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 7, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 47, NextOneIdx = 67 },
            new TreeNode { Value = 0, NextZeroIdx = 48, NextOneIdx = 63 },
            new TreeNode { Value = 0, NextZeroIdx = 49, NextOneIdx = 62 },
            new TreeNode { Value = 8, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 396, NextOneIdx = 51 },
            new TreeNode { Value = 0, NextZeroIdx = 52, NextOneIdx = 309 },
            new TreeNode { Value = 0, NextZeroIdx = 486, NextOneIdx = 53 },
            new TreeNode { Value = 0, NextZeroIdx = 54, NextOneIdx = 307 },
            new TreeNode { Value = 9, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 74, NextOneIdx = 56 },
            new TreeNode { Value = 0, NextZeroIdx = 91, NextOneIdx = 57 },
            new TreeNode { Value = 0, NextZeroIdx = 274, NextOneIdx = 58 },
            new TreeNode { Value = 0, NextZeroIdx = 502, NextOneIdx = 59 },
            new TreeNode { Value = 0, NextZeroIdx = 60, NextOneIdx = 81 },
            new TreeNode { Value = 0, NextZeroIdx = 61, NextOneIdx = 65 },
            new TreeNode { Value = 10, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 11, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 64, NextOneIdx = 66 },
            new TreeNode { Value = 12, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 13, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 14, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 68, NextOneIdx = 71 },
            new TreeNode { Value = 0, NextZeroIdx = 69, NextOneIdx = 70 },
            new TreeNode { Value = 15, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 16, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 72, NextOneIdx = 73 },
            new TreeNode { Value = 17, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 18, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 75, NextOneIdx = 84 },
            new TreeNode { Value = 0, NextZeroIdx = 76, NextOneIdx = 79 },
            new TreeNode { Value = 0, NextZeroIdx = 77, NextOneIdx = 78 },
            new TreeNode { Value = 19, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 20, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 80, NextOneIdx = 83 },
            new TreeNode { Value = 21, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 82, NextOneIdx = 512 },
            new TreeNode { Value = 22, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 23, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 85, NextOneIdx = 88 },
            new TreeNode { Value = 0, NextZeroIdx = 86, NextOneIdx = 87 },
            new TreeNode { Value = 24, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 25, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 89, NextOneIdx = 90 },
            new TreeNode { Value = 26, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 27, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 92, NextOneIdx = 95 },
            new TreeNode { Value = 0, NextZeroIdx = 93, NextOneIdx = 94 },
            new TreeNode { Value = 28, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 29, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 96, NextOneIdx = 97 },
            new TreeNode { Value = 30, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 31, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 133, NextOneIdx = 99 },
            new TreeNode { Value = 0, NextZeroIdx = 100, NextOneIdx = 129 },
            new TreeNode { Value = 0, NextZeroIdx = 258, NextOneIdx = 101 },
            new TreeNode { Value = 0, NextZeroIdx = 102, NextOneIdx = 126 },
            new TreeNode { Value = 0, NextZeroIdx = 103, NextOneIdx = 112 },
            new TreeNode { Value = 32, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 105, NextOneIdx = 119 },
            new TreeNode { Value = 0, NextZeroIdx = 106, NextOneIdx = 107 },
            new TreeNode { Value = 33, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 34, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 271, NextOneIdx = 109 },
            new TreeNode { Value = 0, NextZeroIdx = 110, NextOneIdx = 164 },
            new TreeNode { Value = 35, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 36, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 37, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 114, NextOneIdx = 124 },
            new TreeNode { Value = 0, NextZeroIdx = 115, NextOneIdx = 122 },
            new TreeNode { Value = 38, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 165, NextOneIdx = 117 },
            new TreeNode { Value = 0, NextZeroIdx = 118, NextOneIdx = 123 },
            new TreeNode { Value = 39, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 120, NextOneIdx = 121 },
            new TreeNode { Value = 40, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 41, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 42, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 43, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 125, NextOneIdx = 157 },
            new TreeNode { Value = 44, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 127, NextOneIdx = 128 },
            new TreeNode { Value = 45, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 46, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 130, NextOneIdx = 144 },
            new TreeNode { Value = 0, NextZeroIdx = 131, NextOneIdx = 141 },
            new TreeNode { Value = 0, NextZeroIdx = 132, NextOneIdx = 140 },
            new TreeNode { Value = 47, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 134, NextOneIdx = 229 },
            new TreeNode { Value = 0, NextZeroIdx = 135, NextOneIdx = 138 },
            new TreeNode { Value = 0, NextZeroIdx = 136, NextOneIdx = 137 },
            new TreeNode { Value = 48, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 49, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 139, NextOneIdx = 227 },
            new TreeNode { Value = 50, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 51, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 142, NextOneIdx = 143 },
            new TreeNode { Value = 52, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 53, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 145, NextOneIdx = 148 },
            new TreeNode { Value = 0, NextZeroIdx = 146, NextOneIdx = 147 },
            new TreeNode { Value = 54, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 55, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 149, NextOneIdx = 150 },
            new TreeNode { Value = 56, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 57, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 160, NextOneIdx = 152 },
            new TreeNode { Value = 0, NextZeroIdx = 246, NextOneIdx = 153 },
            new TreeNode { Value = 0, NextZeroIdx = 256, NextOneIdx = 154 },
            new TreeNode { Value = 0, NextZeroIdx = 155, NextOneIdx = 170 },
            new TreeNode { Value = 0, NextZeroIdx = 156, NextOneIdx = 169 },
            new TreeNode { Value = 58, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 59, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 159, NextOneIdx = 226 },
            new TreeNode { Value = 60, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 161, NextOneIdx = 232 },
            new TreeNode { Value = 0, NextZeroIdx = 162, NextOneIdx = 224 },
            new TreeNode { Value = 0, NextZeroIdx = 163, NextOneIdx = 168 },
            new TreeNode { Value = 61, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 62, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 63, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 167, NextOneIdx = 215 },
            new TreeNode { Value = 64, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 65, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 66, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 171, NextOneIdx = 172 },
            new TreeNode { Value = 67, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 68, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 174, NextOneIdx = 189 },
            new TreeNode { Value = 0, NextZeroIdx = 175, NextOneIdx = 182 },
            new TreeNode { Value = 0, NextZeroIdx = 176, NextOneIdx = 179 },
            new TreeNode { Value = 0, NextZeroIdx = 177, NextOneIdx = 178 },
            new TreeNode { Value = 69, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 70, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 180, NextOneIdx = 181 },
            new TreeNode { Value = 71, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 72, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 183, NextOneIdx = 186 },
            new TreeNode { Value = 0, NextZeroIdx = 184, NextOneIdx = 185 },
            new TreeNode { Value = 73, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 74, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 187, NextOneIdx = 188 },
            new TreeNode { Value = 75, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 76, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 190, NextOneIdx = 197 },
            new TreeNode { Value = 0, NextZeroIdx = 191, NextOneIdx = 194 },
            new TreeNode { Value = 0, NextZeroIdx = 192, NextOneIdx = 193 },
            new TreeNode { Value = 77, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 78, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 195, NextOneIdx = 196 },
            new TreeNode { Value = 79, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 80, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 198, NextOneIdx = 201 },
            new TreeNode { Value = 0, NextZeroIdx = 199, NextOneIdx = 200 },
            new TreeNode { Value = 81, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 82, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 202, NextOneIdx = 203 },
            new TreeNode { Value = 83, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 84, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 205, NextOneIdx = 242 },
            new TreeNode { Value = 0, NextZeroIdx = 206, NextOneIdx = 209 },
            new TreeNode { Value = 0, NextZeroIdx = 207, NextOneIdx = 208 },
            new TreeNode { Value = 85, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 86, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 210, NextOneIdx = 213 },
            new TreeNode { Value = 87, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 212, NextOneIdx = 214 },
            new TreeNode { Value = 88, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 89, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 90, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 91, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 217, NextOneIdx = 286 },
            new TreeNode { Value = 0, NextZeroIdx = 218, NextOneIdx = 276 },
            new TreeNode { Value = 0, NextZeroIdx = 219, NextOneIdx = 410 },
            new TreeNode { Value = 92, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 221, NextOneIdx = 273 },
            new TreeNode { Value = 93, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 223, NextOneIdx = 272 },
            new TreeNode { Value = 94, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 225, NextOneIdx = 228 },
            new TreeNode { Value = 95, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 96, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 97, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 98, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 230, NextOneIdx = 240 },
            new TreeNode { Value = 0, NextZeroIdx = 231, NextOneIdx = 235 },
            new TreeNode { Value = 99, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 233, NextOneIdx = 237 },
            new TreeNode { Value = 0, NextZeroIdx = 234, NextOneIdx = 236 },
            new TreeNode { Value = 100, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 101, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 102, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 238, NextOneIdx = 239 },
            new TreeNode { Value = 103, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 104, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 241, NextOneIdx = 252 },
            new TreeNode { Value = 105, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 243, NextOneIdx = 254 },
            new TreeNode { Value = 0, NextZeroIdx = 244, NextOneIdx = 245 },
            new TreeNode { Value = 106, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 107, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 247, NextOneIdx = 250 },
            new TreeNode { Value = 0, NextZeroIdx = 248, NextOneIdx = 249 },
            new TreeNode { Value = 108, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 109, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 251, NextOneIdx = 253 },
            new TreeNode { Value = 110, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 111, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 112, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 255, NextOneIdx = 262 },
            new TreeNode { Value = 113, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 257, NextOneIdx = 261 },
            new TreeNode { Value = 114, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 259, NextOneIdx = 260 },
            new TreeNode { Value = 115, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 116, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 117, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 118, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 264, NextOneIdx = 267 },
            new TreeNode { Value = 0, NextZeroIdx = 265, NextOneIdx = 266 },
            new TreeNode { Value = 119, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 120, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 268, NextOneIdx = 269 },
            new TreeNode { Value = 121, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 122, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 123, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 124, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 125, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 126, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 275, NextOneIdx = 459 },
            new TreeNode { Value = 127, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 436, NextOneIdx = 277 },
            new TreeNode { Value = 0, NextZeroIdx = 278, NextOneIdx = 285 },
            new TreeNode { Value = 128, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 372, NextOneIdx = 280 },
            new TreeNode { Value = 0, NextZeroIdx = 281, NextOneIdx = 332 },
            new TreeNode { Value = 0, NextZeroIdx = 282, NextOneIdx = 291 },
            new TreeNode { Value = 0, NextZeroIdx = 473, NextOneIdx = 283 },
            new TreeNode { Value = 0, NextZeroIdx = 284, NextOneIdx = 290 },
            new TreeNode { Value = 129, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 130, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 287, NextOneIdx = 328 },
            new TreeNode { Value = 0, NextZeroIdx = 288, NextOneIdx = 388 },
            new TreeNode { Value = 0, NextZeroIdx = 289, NextOneIdx = 345 },
            new TreeNode { Value = 131, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 132, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 292, NextOneIdx = 296 },
            new TreeNode { Value = 0, NextZeroIdx = 293, NextOneIdx = 294 },
            new TreeNode { Value = 133, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 134, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 135, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 297, NextOneIdx = 313 },
            new TreeNode { Value = 136, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 299, NextOneIdx = 300 },
            new TreeNode { Value = 137, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 138, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 302, NextOneIdx = 305 },
            new TreeNode { Value = 0, NextZeroIdx = 303, NextOneIdx = 304 },
            new TreeNode { Value = 139, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 140, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 306, NextOneIdx = 308 },
            new TreeNode { Value = 141, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 142, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 143, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 310, NextOneIdx = 319 },
            new TreeNode { Value = 0, NextZeroIdx = 311, NextOneIdx = 312 },
            new TreeNode { Value = 144, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 145, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 146, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 315, NextOneIdx = 350 },
            new TreeNode { Value = 0, NextZeroIdx = 316, NextOneIdx = 325 },
            new TreeNode { Value = 0, NextZeroIdx = 317, NextOneIdx = 322 },
            new TreeNode { Value = 0, NextZeroIdx = 318, NextOneIdx = 321 },
            new TreeNode { Value = 147, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 320, NextOneIdx = 341 },
            new TreeNode { Value = 148, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 149, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 323, NextOneIdx = 324 },
            new TreeNode { Value = 150, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 151, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 326, NextOneIdx = 338 },
            new TreeNode { Value = 0, NextZeroIdx = 327, NextOneIdx = 336 },
            new TreeNode { Value = 152, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 465, NextOneIdx = 329 },
            new TreeNode { Value = 0, NextZeroIdx = 330, NextOneIdx = 355 },
            new TreeNode { Value = 0, NextZeroIdx = 331, NextOneIdx = 344 },
            new TreeNode { Value = 153, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 333, NextOneIdx = 347 },
            new TreeNode { Value = 0, NextZeroIdx = 334, NextOneIdx = 342 },
            new TreeNode { Value = 0, NextZeroIdx = 335, NextOneIdx = 337 },
            new TreeNode { Value = 154, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 155, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 156, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 339, NextOneIdx = 340 },
            new TreeNode { Value = 157, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 158, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 159, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 343, NextOneIdx = 346 },
            new TreeNode { Value = 160, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 161, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 162, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 163, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 348, NextOneIdx = 360 },
            new TreeNode { Value = 0, NextZeroIdx = 349, NextOneIdx = 359 },
            new TreeNode { Value = 164, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 351, NextOneIdx = 369 },
            new TreeNode { Value = 0, NextZeroIdx = 352, NextOneIdx = 357 },
            new TreeNode { Value = 0, NextZeroIdx = 353, NextOneIdx = 354 },
            new TreeNode { Value = 165, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 166, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 356, NextOneIdx = 366 },
            new TreeNode { Value = 167, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 358, NextOneIdx = 368 },
            new TreeNode { Value = 168, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 169, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 361, NextOneIdx = 367 },
            new TreeNode { Value = 170, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 363, NextOneIdx = 417 },
            new TreeNode { Value = 0, NextZeroIdx = 364, NextOneIdx = 449 },
            new TreeNode { Value = 0, NextZeroIdx = 365, NextOneIdx = 434 },
            new TreeNode { Value = 171, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 172, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 173, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 174, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 370, NextOneIdx = 385 },
            new TreeNode { Value = 0, NextZeroIdx = 371, NextOneIdx = 383 },
            new TreeNode { Value = 175, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 373, NextOneIdx = 451 },
            new TreeNode { Value = 0, NextZeroIdx = 374, NextOneIdx = 381 },
            new TreeNode { Value = 0, NextZeroIdx = 375, NextOneIdx = 376 },
            new TreeNode { Value = 176, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 177, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 378, NextOneIdx = 393 },
            new TreeNode { Value = 0, NextZeroIdx = 379, NextOneIdx = 390 },
            new TreeNode { Value = 0, NextZeroIdx = 380, NextOneIdx = 384 },
            new TreeNode { Value = 178, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 382, NextOneIdx = 437 },
            new TreeNode { Value = 179, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 180, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 181, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 386, NextOneIdx = 387 },
            new TreeNode { Value = 182, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 183, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 389, NextOneIdx = 409 },
            new TreeNode { Value = 184, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 391, NextOneIdx = 392 },
            new TreeNode { Value = 185, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 186, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 394, NextOneIdx = 400 },
            new TreeNode { Value = 0, NextZeroIdx = 395, NextOneIdx = 399 },
            new TreeNode { Value = 187, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 397, NextOneIdx = 412 },
            new TreeNode { Value = 0, NextZeroIdx = 398, NextOneIdx = 402 },
            new TreeNode { Value = 188, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 189, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 401, NextOneIdx = 411 },
            new TreeNode { Value = 190, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 191, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 404, NextOneIdx = 427 },
            new TreeNode { Value = 0, NextZeroIdx = 405, NextOneIdx = 424 },
            new TreeNode { Value = 0, NextZeroIdx = 406, NextOneIdx = 421 },
            new TreeNode { Value = 0, NextZeroIdx = 407, NextOneIdx = 408 },
            new TreeNode { Value = 192, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 193, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 194, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 195, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 196, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 413, NextOneIdx = 474 },
            new TreeNode { Value = 197, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 415, NextOneIdx = 475 },
            new TreeNode { Value = 0, NextZeroIdx = 416, NextOneIdx = 471 },
            new TreeNode { Value = 198, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 481, NextOneIdx = 418 },
            new TreeNode { Value = 0, NextZeroIdx = 419, NextOneIdx = 478 },
            new TreeNode { Value = 0, NextZeroIdx = 420, NextOneIdx = 435 },
            new TreeNode { Value = 199, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 422, NextOneIdx = 423 },
            new TreeNode { Value = 200, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 201, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 425, NextOneIdx = 438 },
            new TreeNode { Value = 0, NextZeroIdx = 426, NextOneIdx = 433 },
            new TreeNode { Value = 202, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 455, NextOneIdx = 428 },
            new TreeNode { Value = 0, NextZeroIdx = 490, NextOneIdx = 429 },
            new TreeNode { Value = 0, NextZeroIdx = 511, NextOneIdx = 430 },
            new TreeNode { Value = 0, NextZeroIdx = 431, NextOneIdx = 432 },
            new TreeNode { Value = 203, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 204, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 205, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 206, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 207, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 208, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 209, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 439, NextOneIdx = 446 },
            new TreeNode { Value = 210, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 441, NextOneIdx = 494 },
            new TreeNode { Value = 0, NextZeroIdx = 442, NextOneIdx = 461 },
            new TreeNode { Value = 0, NextZeroIdx = 443, NextOneIdx = 447 },
            new TreeNode { Value = 0, NextZeroIdx = 444, NextOneIdx = 445 },
            new TreeNode { Value = 211, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 212, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 213, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 448, NextOneIdx = 460 },
            new TreeNode { Value = 214, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 450, NextOneIdx = 467 },
            new TreeNode { Value = 215, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 452, NextOneIdx = 469 },
            new TreeNode { Value = 0, NextZeroIdx = 453, NextOneIdx = 454 },
            new TreeNode { Value = 216, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 217, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 456, NextOneIdx = 484 },
            new TreeNode { Value = 0, NextZeroIdx = 457, NextOneIdx = 458 },
            new TreeNode { Value = 218, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 219, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 220, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 221, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 462, NextOneIdx = 488 },
            new TreeNode { Value = 0, NextZeroIdx = 463, NextOneIdx = 464 },
            new TreeNode { Value = 222, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 223, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 466, NextOneIdx = 468 },
            new TreeNode { Value = 224, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 225, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 226, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 470, NextOneIdx = 472 },
            new TreeNode { Value = 227, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 228, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 229, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 230, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 231, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 476, NextOneIdx = 477 },
            new TreeNode { Value = 232, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 233, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 479, NextOneIdx = 480 },
            new TreeNode { Value = 234, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 235, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 482, NextOneIdx = 483 },
            new TreeNode { Value = 236, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 237, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 485, NextOneIdx = 487 },
            new TreeNode { Value = 238, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 239, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 240, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 489, NextOneIdx = 493 },
            new TreeNode { Value = 241, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 491, NextOneIdx = 492 },
            new TreeNode { Value = 242, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 243, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 244, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 495, NextOneIdx = 503 },
            new TreeNode { Value = 0, NextZeroIdx = 496, NextOneIdx = 499 },
            new TreeNode { Value = 0, NextZeroIdx = 497, NextOneIdx = 498 },
            new TreeNode { Value = 245, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 246, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 500, NextOneIdx = 501 },
            new TreeNode { Value = 247, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 248, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 249, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 504, NextOneIdx = 507 },
            new TreeNode { Value = 0, NextZeroIdx = 505, NextOneIdx = 506 },
            new TreeNode { Value = 250, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 251, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 0, NextZeroIdx = 508, NextOneIdx = 509 },
            new TreeNode { Value = 252, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 253, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 254, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 255, NextZeroIdx = 0, NextOneIdx = 0 },
            new TreeNode { Value = 256, NextZeroIdx = 0, NextOneIdx = 0 }
        };

        //static HuffmanEncoder()
        //{
        //    BuildTree();
        //}
        //
        //private static void BuildTree()
        //{
        //    // Add root
        //    entries.Add(new TreeNode());
        //
        //    for (int i = 0; i < StaticTable.Length; ++i)
        //    {
        //        var tableEntry = StaticTable[i];
        //        var currentNode = entries[0];
        //        int currentNodeIdx = 0;
        //
        //        for (byte bitIdx = 1; bitIdx <= tableEntry.Bits; bitIdx++)
        //        {
        //            byte bit = tableEntry.GetBitAtIdx(bitIdx);
        //
        //            switch(bit)
        //            {
        //                case 0:
        //                    if (currentNode.NextZeroIdx == 0)
        //                    {
        //                        currentNode.NextZeroIdx = (UInt16)entries.Count;
        //                        entries[currentNodeIdx] = currentNode;
        //                        entries.Add(new TreeNode());
        //                    }
        //
        //                    currentNodeIdx = currentNode.NextZeroIdx;
        //                    currentNode = entries[currentNodeIdx];
        //                    break;
        //
        //                case 1:
        //                    if (currentNode.NextOneIdx == 0)
        //                    {
        //                        currentNode.NextOneIdx = (UInt16)entries.Count;
        //                        entries[currentNodeIdx] = currentNode;
        //                        entries.Add(new TreeNode());
        //                    }
        //
        //                    currentNodeIdx = currentNode.NextOneIdx;
        //                    currentNode = entries[currentNodeIdx];
        //                    break;
        //
        //                default:
        //                    HTTPManager.Logger.Information("HuffmanEncoder", "BuildTree - GetBitAtIdx returned with an unsupported value: " + bit);
        //                    break;
        //            }
        //        }
        //
        //        entries[currentNodeIdx] = new TreeNode { Value = (UInt16)i };
        //
        //        //HTTPManager.Logger.Information("HuffmanEncoder", string.Format("BuildTree - {0} - Entry({1}) added to idx: {2}", i, entries[currentNodeIdx], currentNodeIdx));
        //    }
        //
        //    //HTTPManager.Logger.Information("HuffmanEncoder", "BuildTree - entries: " + entries.Count);
        //    //for (int i = 0; i < entries.Count; ++i)
        //    //    HTTPManager.Logger.Information("HuffmanEncoder", string.Format("{0} - Entry : {1}", i, entries[i]));
        //    System.Text.StringBuilder sb = new System.Text.StringBuilder();
        //    for (int i = 0; i < entries.Count; ++i)
        //    {
        //        sb.AppendFormat("new TreeNode {{ Value = {0}, NextZeroIdx = {1}, NextOneIdx = {2} }},\n", entries[i].Value, entries[i].NextZeroIdx, entries[i].NextOneIdx);
        //    }
        //    UnityEngine.Debug.Log(sb.ToString());
        //}

        public static TreeNode GetRoot()
        {
            return HuffmanTree[0];
        }

        public static TreeNode GetNext(TreeNode current, byte bit)
        {
            switch(bit)
            {
                case 0:
                    return HuffmanTree[current.NextZeroIdx];
                case 1:
                    return HuffmanTree[current.NextOneIdx];
            }

            throw new Exception("HuffmanEncoder - GetNext - unsupported bit: " + bit);
        }

        public static TableEntry GetEntryForCodePoint(UInt16 codePoint)
        {
            return StaticTable[codePoint];
        }
    }
}

#endif